package com.cskaoyan.java.object._1getclass;

/**
 * Object类的getClass方法
 * 方法的声明:
 * public final native Class<?> getClass();
 * 解释:
 *      1.方法的访问权限修饰符是public 这意味它可以随意调用 不用关心权限问题
 *      2.final修饰它 表示不能被重写,但是可以继承
 *      3.native关键字表示它是一个本地方法,它也没有方法体
 *      4.Class<?> 是返回值类型,表示方法返回一个java.lang.Class对象
 *          <?>是泛型,还没学,今天的课程全部去掉
 *          Java的泛型是伪泛型,它只影响程序的编译,不会影响程序的执行
 *      5.方法不需要任何传参,是无参方法
 *
 * 接下来,思考两个问题:
 *      1.什么是Class对象,它是怎么来的?
 *      2.Class对象有什么作用?
 * 以上两个问题搞清楚,getClass方法就学会了
 *
 * 类加载是JVM认识了解一个类型的过程,细分它的流程,可以分为三大流程:
 *      1.加载
 *      2.连接(准备,验证,解析),静态成员变量的默认初始化
 *      3.初始化,为了执行static相关,静态成员变量的显式赋值以及静态代码块
 * 通过以上流程JVM完成对一个类的类加载,完成类加载后,JVM就能够获取类型信息,完成一系列的操作
 *
 * 实际开发中是存在以下需求:
 * 程序员希望能够在程序的运行期间,动态得获取某个类的类型信息,来动态的完成一些操作.
 * 这时为了满足程序员的这个需求,JVM在类加载某个类的同时(加载阶段)
 * 会在堆上自动创建一个封装了该类类型信息的对象
 * 这个对象就是这个类的Class对象
 * Class对象当中封装了某个类的类型信息,比如类名是什么,在哪个包,有哪些方法,构造器等
 * Class对象也被称之某个类的"运行时类对象",简称"类对象"
 *
 * Class对象中封装了类型信息,所以获取Class对象,就可以获取该类的类型信息,然后进行一些操作
 * 这种在程序运行期间,通过获取Class对象,获取类型信息,然后进行一些操作的技术,就是Java中的反射
 * 反射实际上就是Class类API,就是Class类的方法调用
 *
 * 细节(注意事项):
 *      1.Class对象是JVM创建的,在类加载的加载阶段创建的,它不是getClass方法创建的
 *          getClass方法只是通过一个本地方法获取这个对象
 *
 *      2.(重点)某个类的类加载只有一次,所以某个类的运行时类对象Class对象是唯一的
 *          这是Class对象最重要的特点.
 *          同种类型对象的引用调用getClass方法,"=="连接 返回true
 *          不同种类型对象的引用调用getClass方法,"=="连接 返回false
 *          实际开发中,通过getClass方法获取Class对象是很少见的操作
 *          getClass方法在实际开发中,最常用于判断两个引用指向的对象是否是同种类型的对象
 *
 *       3.演示一下Class类API的使用
 *       可以用来获取类型信息
 *       // 获取类的全限定类名
 *       String getName()
 *      // 获取类名
 *      String getSimpleName()
 *
 * @since 10:56
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // Student类的对象
        Student s = new Student();
        Student s2 = new Student();
        // Student类对象,Student运行时类对象,Student的Class对
        Class stuClazz = s.getClass();
        Class stuClazz2 = s2.getClass();
        System.out.println(stuClazz == stuClazz2);

        Teacher t = new Teacher();
        Class teacherClazz = t.getClass();
        System.out.println(stuClazz == teacherClazz);

        System.out.println("--------------");
        System.out.println(judgeType(s, s2));
        System.out.println(judgeType(s, t));

        System.out.println("------------------");
        System.out.println(stuClazz.getName());
        System.out.println(teacherClazz.getSimpleName());
    }

    // 该方法需要传入两个对象,如果两个对象是同种类型对象返回true,否则返回false
    public static boolean judgeType(Object o1, Object o2) {
        return o1.getClass() == o2.getClass();
    }
}

class Student {

}

class Teacher {
}